
#include "ControlDef.h"

//已删除全部注释

//CSpListBox
//////////////////////////////////////////////////////////////////////////
void CSpListBox::CreateItem(int Id,int RecordNum)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it==ListBoxItems.end())
	{
		ItemDesc* NewItem=new ItemDesc;
		NewItem->Id=Id;
		NewItem->RecordNum=RecordNum;
		NewItem->Records=new WCHAR*[RecordNum];
		NewItem->Color=new DWORD[RecordNum];
		for (int i=0;i<RecordNum;i++)
		{
			NewItem->Records[i]=NULL;
			NewItem->Color[i]=0xFF000000;
		}
		NewItem->Height=-1;
		NewItem->Visible=TRUE;
		NewItem->UserData=NULL;
		ListBoxItems.insert(std::make_pair(Id,NewItem));
		InvalidPos=TRUE;
	}
}

void CSpListBox::DeleteItem(int Id)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it!=ListBoxItems.end())
	{
		ItemDesc* Item=it->second;
		SelectItem(Item->Id,FALSE);
		for (int i=0;i<Item->RecordNum;i++)
		{
			if (Item->Records[i]!=NULL)
				delete[] Item->Records[i];
		}
		delete[] Item->Records;
		delete[] Item->Color;
		delete Item;
		ListBoxItems.erase(it);
		InvalidPos=TRUE;
	}
}

void CSpListBox::ClearItem()
{
	std::map<int,ItemDesc*>::iterator it;
	for (it=ListBoxItems.begin();it!=ListBoxItems.end();it++)
	{
		ItemDesc* Item=it->second;
		for (int i=0;i<Item->RecordNum;i++)
		{
			if (Item->Records[i]!=NULL)
				delete[] Item->Records[i];
		}
		delete[] Item->Records;
		delete[] Item->Color;
		delete Item;
	}
	ListBoxItems.clear();
	InvalidPos=TRUE;
}

void CSpListBox::SetItemContent(int Id,int Index,WCHAR* Text,DWORD Color)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it!=ListBoxItems.end())
	{
		ItemDesc* Item=it->second;
		if (Item->Records[Index]!=NULL)
			delete[] Item->Records[Index];
		Item->Records[Index]=wstrdup(Text);
		Item->Color[Index]=Color;
		HoverId=-1;
	}
}

void CSpListBox::ShowItem(int Id,BOOL Visible)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it!=ListBoxItems.end())
	{
		ItemDesc* Item=it->second;
		if (Item->Visible!=Visible)
		{
			if (!Visible)
				SelectItem(Item->Id,FALSE);
			Item->Visible=Visible;
			HoverId=-1;
			InvalidPos=TRUE;
		}
	}
}

void CSpListBox::SetItemData(int Id,PVOID UserData)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it!=ListBoxItems.end())
	{
		ItemDesc* Item=it->second;
		Item->UserData=UserData;
	}
}

PVOID CSpListBox::GetItemData(int Id)
{
	std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(Id);
	if (it!=ListBoxItems.end())
	{
		ItemDesc* Item=it->second;
		return Item->UserData;
	}
	return NULL;
}

void CSpListBox::SetSelectLimit(int MaxNum)
{
	if (MaxNum<1 || SelectLimit==MaxNum)
		return ;
	int DelNum=SelectedNum-MaxNum;
	if (DelNum>0)
	{
		for (int i=0;i<MaxNum;i++)
			SelectIdArray[i]=SelectIdArray[i+DelNum];
	}
	SelectLimit=MaxNum;
	delete[] SelectIdArray;
	delete[] SelectIdArray2;
	SelectIdArray=new int[MaxNum];
	SelectIdArray2=new int[MaxNum];
	SelectChangeCall();
}

BOOL CSpListBox::IsItemSelected(int Id)
{
	if (SelectedNum==0)
		return FALSE;
	for (int i=0;i<SelectedNum;i++)
	{
		if (SelectIdArray[i]==Id)
			return TRUE;
	}
	return FALSE;
}

void CSpListBox::SelectItem(int Id,BOOL Select)
{
	for (int i=0;i<SelectedNum;i++)
	{
		if (SelectIdArray[i]==Id)
		{
			if (Select==FALSE)
			{
				for (int j=i;j<SelectedNum-1;j++)
					SelectIdArray[j]=SelectIdArray[j+1];
				SelectedNum--;
				SelectChangeCall();
			}
			return ;
		}
	}
	if (Select==FALSE)
		return ;
	if (SelectedNum==SelectLimit)
	{
		for (int i=0;i<SelectedNum-1;i++)
			SelectIdArray[i]=SelectIdArray[i+1];
		SelectIdArray[SelectedNum-1]=Id;
		SelectChangeCall();
	}
	else
	{
		SelectIdArray[SelectedNum]=Id;
		SelectedNum++;
		SelectChangeCall();
	}
}

int CSpListBox::GetSelectedItem(int* IdArrayOut)
{
	for (int i=0;i<SelectedNum;i++)
		IdArrayOut[i]=SelectIdArray[i];
	for (int i=SelectedNum;i<SelectLimit;i++)
		IdArrayOut[i]=-1;
	return SelectedNum;
}

void CSpListBox::CancelAllSelect()
{
	SelectedNum=0;
	SelectChangeCall();
}

void CSpListBox::SelectChangeCall()
{
	for (int i=0;i<SelectedNum;i++)
		SelectIdArray2[i]=SelectIdArray[i];
	for (int i=SelectedNum;i<SelectLimit;i++)
		SelectIdArray2[i]=-1;
	if (EventHandler!=NULL)
		EventHandler(this,EvtSpSelectChange,(PVOID)SelectIdArray2,(PVOID)SelectedNum);
}

CSpListBox::CSpListBox(WCHAR* Name,int X,int Y,int Width,int Height)
{
	Type=CT_SpListBox;
	this->Name=wstrdup(Name);
	this->X=X;
	this->Y=Y;
	this->Width=Width;
	this->Height=Height;
	this->Scrollable=TRUE;

	ScrollCpnt=new VScrollComponent(0,this,Width-VScrollComponent::ScrollWidth-BodyPadding,BodyPadding);
	ScrollCpnt->Visible=FALSE;
	SubCpnt[0]=ScrollCpnt;
	ComponentNum=1;

	SelectLimit=1;
	SelectedNum=0;
	SelectIdArray=new int[1];
	SelectIdArray2=new int[1];
	SpViewPos=0;
	ItemTotalHeight=0;
	HoverId=-1;
	PushedForClick=FALSE;
	PushedItemId=-1;
	InvalidPos=TRUE;

	ItemAreaWidth=Width-BodyPadding*2-ScrollWidth;
	ItemAreaHeight=Height-BodyPadding*2;

	FontText=ResMgr->LoadFontR(L"宋体-14");
	ImgBack=NULL;
	BackMode=0;
	ImgItemNormal=ResMgr->LoadScale9R(L"列表元素Normal");
	ImgItemHover=ResMgr->LoadScale9R(L"列表元素Hover");
	ImgItemSelect=ResMgr->LoadScale9R(L"列表元素Select");
	ImgItemSelHover=ResMgr->LoadScale9R(L"列表元素SelHover");
}

CSpListBox::~CSpListBox()
{
	ClearItem();
	delete[] SelectIdArray;
	delete[] SelectIdArray2;
	ResMgr->ReleaseScale9R(ImgItemNormal);
	ResMgr->ReleaseScale9R(ImgItemHover);
	ResMgr->ReleaseScale9R(ImgItemSelect);
	ResMgr->ReleaseScale9R(ImgItemSelHover);
	if (this->ImgBack!=NULL)
		ResMgr->ReleaseImageNoType(this->ImgBack);
	ResMgr->ReleaseFontR(FontText);
	delete ScrollCpnt;
	delete[] Name;
}

void CSpListBox::SetBackImage(ImageR_t* ImgBack,int BackMode)
{
	if (this->ImgBack!=NULL)
		ResMgr->ReleaseImageNoType(this->ImgBack);
	this->ImgBack=ImgBack;
	this->BackMode=BackMode;
}

int CSpListBox::CalcItemHeight(CSpListBox::ItemDesc* Item)
{
	int FontHeight=D2dMgr->GetFontHeight(FontText);
	int TextAreaWidth=ItemAreaWidth-ItemPadding*2;
	int ItemHeight=ItemPadding;
	for (int i=0;i<Item->RecordNum;i++)
	{
		if (Item->Records[i]!=NULL)
		{
			ItemHeight+=D2dMgr->CalcAutoDrawTextHeight(Item->Records[i],-1,TextAreaWidth,0,0,FontText);
			ItemHeight+=ParaSpace;
		}
	}
	ItemHeight-=ParaSpace;
	ItemHeight+=ItemPadding;
	return ItemHeight;
}

void CSpListBox::DrawItem(int ItemX,int ItemY,CSpListBox::ItemDesc* Item)
{
	BOOL ItemSelected=IsItemSelected(Item->Id);
	ImageR_t* ImgDraw=ImgItemNormal;
	if (ItemSelected && Item->Id==HoverId)
		ImgDraw=ImgItemSelHover;
	else if (ItemSelected)
		ImgDraw=ImgItemSelect;
	else if (Item->Id==HoverId)
		ImgDraw=ImgItemHover;
	D2dMgr->SetImageOpacity(1.0f);
	D2dMgr->DrawImage(ItemX,ItemY,ItemAreaWidth,Item->Height,ImgDraw);

	int FontHeight=D2dMgr->GetFontHeight(FontText);	
	int TextAreaWidth=ItemAreaWidth-ItemPadding*2;
	int DrawTextX=ItemX+ItemPadding;
	int DrawTextY=ItemY+ItemPadding;

	for (int i=0;i<Item->RecordNum;i++)
	{
		if (Item->Records[i]!=NULL)
		{			
			int RecordHeight=D2dMgr->CalcAutoDrawTextHeight(Item->Records[i],-1,TextAreaWidth,0,0,FontText);
			D2dMgr->SetColor(Item->Color[i]);
			D2dMgr->AutoDrawText(Item->Records[i],-1,DrawTextX,DrawTextY,TextAreaWidth,RecordHeight,0,0,FontText);
			DrawTextY+=RecordHeight;
			DrawTextY+=ParaSpace;
		}
	}
}

void CSpListBox::ApplyItemChange()
{
	int OldTotalHeight=0;
	BOOL Adjust=TRUE;
	int AdjustHeight=0;

	int NewPos=0;
	int NewTotalHeight=0;
	std::map<int,ItemDesc*>::iterator it;
	for (it=ListBoxItems.begin();it!=ListBoxItems.end();it++)
	{
		ItemDesc* Item=it->second;
		int NewHeight=CalcItemHeight(Item);

		if (InvalidPos==FALSE && Adjust)
		{
			if (Item->Visible)
			{
				if (OldTotalHeight+Item->Height>=SpViewPos)
				{
					if (OldTotalHeight+NewHeight<SpViewPos)
						AdjustHeight+=(OldTotalHeight+NewHeight)-SpViewPos;

					NewPos=SpViewPos+AdjustHeight;
					Adjust=FALSE;
				}
				AdjustHeight+=NewHeight-Item->Height;

				OldTotalHeight+=Item->Height;
			}
		}

		Item->Height=NewHeight;
		if (Item->Visible)
			NewTotalHeight+=Item->Height;
	}
	InvalidPos=FALSE;

	if (ItemTotalHeight!=NewTotalHeight)
	{
		ItemTotalHeight=NewTotalHeight;
		ScrollCpnt->Visible=FALSE;
		if (ItemTotalHeight>ItemAreaHeight)
		{
			ScrollCpnt->Visible=TRUE;
			ScrollCpnt->SetScrollParam(ItemAreaHeight,ItemAreaHeight,ItemTotalHeight);
            SpViewPos=-1;
			SetSpViewPos(NewPos);
		}
	}
}

int CSpListBox::ItemMouseHitTest(int ItemAreaPosX,int ItemAreaPosY)
{
	int ItemAreaVirtualPosY=ItemAreaPosY+SpViewPos;
	int ItemPosY=0;
	std::map<int,ItemDesc*>::iterator it;
	for (it=ListBoxItems.begin();it!=ListBoxItems.end();it++)
	{
		ItemDesc* Item=it->second;
		if (Item->Visible)
		{	
			if (PointInRect(ItemAreaPosX,ItemAreaVirtualPosY,BodyPadding,ItemPosY,Width-BodyPadding-ScrollWidth,Item->Height))
				return Item->Id;
			ItemPosY+=Item->Height;
		}
	}
	return -1;
}

void CSpListBox::SetSpViewPos(int NewPos)
{
	if (SpViewPos!=NewPos)
	{
		SpViewPos=NewPos;
		if (SpViewPos<0)
			SpViewPos=0;
		else if (SpViewPos+ItemAreaHeight>ItemTotalHeight)
			SpViewPos=ItemTotalHeight-ItemAreaHeight;
		ScrollCpnt->SyncScrollData((float)SpViewPos/ItemTotalHeight);
	}
}

void CSpListBox::Draw()
{
	D2dMgr->SetColor(0xFFC09000);
	D2dMgr->DrawRectangle(2,2,Width-4,Height-4);
	D2dMgr->SetColor(0xFFB57300);
	D2dMgr->DrawRectangle(1,1,Width-2,Height-2);
	D2dMgr->SetColor(0xFF9D5D00);
	D2dMgr->DrawRectangle(0,0,Width,Height);

	if (ImgBack!=NULL)
	{
		int BackWidth=ResMgr->GetImageWidth(ImgBack);
		int BackHeight=ResMgr->GetImageHeight(ImgBack);
		D2dMgr->SetImageOpacity(1.0f);	
		if (BackMode==0)
		{
			D2dMgr->DrawImage(0,0,Width,Height,ImgBack);
		}
		else if (BackMode==1)
		{
			D2dMgr->DrawImage(Width/2-BackWidth/2,Height/2-BackHeight/2,BackWidth,BackHeight,ImgBack);
		}
		else if (BackMode==2)
		{
			D2dMgr->DrawImage(0,0,BackWidth,BackHeight,ImgBack);
		}
		else if (BackMode==3)
		{
			for (int ImgY=0;ImgY<Height;ImgY+=BackHeight)
				for (int ImgX=0;ImgX<Width;ImgX+=BackWidth)
					D2dMgr->DrawImage(ImgX,ImgY,BackWidth,BackHeight,ImgBack);
		}
	}

	if (!ScrollCpnt->Visible)
	{
		D2dMgr->SetColor(0x80C0C0C0);
		D2dMgr->FillRectangle(Width-ScrollWidth-BodyPadding,BodyPadding,ScrollWidth,Height-BodyPadding*2);
	}

	D2dMgr->PushClip(BodyPadding,BodyPadding,ItemAreaWidth,ItemAreaHeight);

	int CurPos=0;
	std::map<int,ItemDesc*>::iterator it;
	for (it=ListBoxItems.begin();it!=ListBoxItems.end();it++)
	{
		ItemDesc* Item=it->second;
		if (Item->Visible)
		{	
			if (SpViewPos>=CurPos && SpViewPos<CurPos+Item->Height)
				break;
			CurPos+=Item->Height;
		}
	}

	int ItemDrawPos=CurPos-SpViewPos;
	for (it;it!=ListBoxItems.end();it++)
	{
		ItemDesc* Item=it->second;
		if (Item->Visible)
		{
			DrawItem(BodyPadding,ItemDrawPos+BodyPadding,Item);
			ItemDrawPos+=Item->Height;
			if (ItemDrawPos>=ItemAreaHeight)
				break;
		}
	}

	D2dMgr->PopClip();

	if (ScrollCpnt->Visible)
	{
		UiMgr->ShrinkDrawingRect(ScrollCpnt->X,ScrollCpnt->Y,ScrollCpnt->Width,ScrollCpnt->Height);
		ScrollCpnt->Draw();
		UiMgr->RecoverDrawingRect();
	}
}

int CSpListBox::Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2)
{
	if (!Enable)
		return 0;
	if (UIEvent==EvtMouseWheel)
	{
		if (ScrollCpnt->Visible)
			SetSpViewPos(SpViewPos+(int)Param1*50);
	}
	else if (UIEvent==EvtMouseDown || UIEvent==EvtMouseUp || UIEvent==EvtMouseMove || UIEvent==EvtMouseLeave)
	{
		BOOL CpntHitMiss=(UiMgr->ComponentMouseDispatch(this,UIEvent,Param1,Param2)==-1);
		if (CpntHitMiss)
		{
			int MouseX=(int)Param1;
			int MouseY=(int)Param2;
			if (UIEvent==EvtMouseDown)
			{
				if (PointInRect(MouseX,MouseY,BodyPadding,BodyPadding,Width-BodyPadding*2-ScrollWidth,Height-BodyPadding*2))
				{
					PushedForClick=TRUE;
					PushedItemId=ItemMouseHitTest(MouseX-BodyPadding,MouseY-BodyPadding);
				}
			}
			else if (UIEvent==EvtMouseUp)
			{
				if (PushedForClick && PushedItemId!=-1)
				{
					if (ItemMouseHitTest(MouseX-BodyPadding,MouseY-BodyPadding)==PushedItemId)
					{
						std::map<int,ItemDesc*>::iterator it=ListBoxItems.find(PushedItemId);
						BOOL ItemSelected=IsItemSelected(PushedItemId);
						SelectItem(PushedItemId,!ItemSelected);
					}
				}
				PushedForClick=FALSE;
			}
			else if (UIEvent==EvtMouseMove)
			{
				HoverId=ItemMouseHitTest(MouseX-BodyPadding,MouseY-BodyPadding);
			}
			else if (UIEvent==EvtMouseLeave)
			{
				HoverId=-1;
			}
		}
	}
	return 0;
}

int CSpListBox::InternalNotify(int Index,UIEvent_t UIEvent,PVOID Param1,PVOID Param2)
{
	if (Index==0 && UIEvent==EvtScrollTo && (BOOL)Param2==FALSE)
	{
		SetSpViewPos((int)Param1/1000);
	}
	return 0;
}


